package api

import (
	"crypto/md5"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
	"naive-admin-go/db"
	"naive-admin-go/inout"
	"naive-admin-go/model"
	"naive-admin-go/utils"
	"net/http"
)

var Auth = &auth{}

type auth struct {
}

// Captcha生成并返回一个验证码图像。
// 该方法生成一个SVG格式的验证码，并将其保存在会话中，以便后续验证。
// 参数:
//
//	c (*gin.Context): gin的上下文对象，用于处理HTTP请求和响应。
func (auth) Captcha(c *gin.Context) {
	// 生成SVG验证码图像和对应的文本代码。
	svg, code := utils.GenerateSVG(80, 40)

	// 获取默认的会话对象。
	session := sessions.Default(c)

	// 将验证码文本代码保存到会话中，以便后续验证用户输入。
	session.Set("captch", code)

	// 保存会话。
	session.Save()

	// 设置响应头的Content-Type为"image/svg+xml"，表明返回的内容是SVG图像。
	c.Header("Content-Type", "image/svg+xml; charset=utf-8")

	// 将SVG格式的验证码图像作为HTTP响应的主体返回给客户端。
	c.Data(http.StatusOK, "image/svg+xml", svg)
}

// Login 处理用户登录请求
// c 是gin框架的Context类型，用于处理HTTP请求和响应
func (auth) Login(c *gin.Context) {
	// 定义一个接收登录参数的结构体变量
	var params inout.LoginReq
	// 从请求中绑定登录参数到params，如果绑定失败则返回错误信息
	err := c.Bind(&params)
	if err != nil {
		Resp.Err(c, 20001, err.Error())
		return
	}

	// 获取默认的gin-session
	session := sessions.Default(c)
	// 检查验证码，如果不匹配则返回错误信息
	if params.Captcha != session.Get("captch") {
		Resp.Err(c, 20001, "验证码不正确")
		return
	}

	// 定义一个指向用户模型的指针，用于存储查询结果
	var info *model.User
	// 使用gorm ORM框架查询数据库，根据用户名查找用户
	db.Dao.Model(model.User{}).
		Where("username =? ", params.Username).
		Find(&info)
	// 如果找不到用户（ID为0），则返回错误信息
	if info.ID == 0 {
		Resp.Err(c, 20001, "账号或密码不正确")
		return
	}

	// 使用bcrypt包比较数据库中的密码和请求中的密码，如果比较失败则返回错误信息
	err = bcrypt.CompareHashAndPassword([]byte(info.Password), []byte(params.Password))
	if err != nil {
		Resp.Err(c, 20001, "账号或密码不正确")
		return
	}

	// 如果一切验证通过，生成JWT访问令牌并返回成功响应
	Resp.Succ(c, inout.LoginRes{
		AccessToken: utils.GenerateToken(info.ID),
	})
}

// password处理密码修改请求
// 参数:
//   - c: gin.Context对象，包含请求和响应上下文
//
// 功能:
//   - 绑定请求参数
//   - 验证旧密码是否正确
//   - 更新密码（如果旧密码验证通过）
//   - 返回操作结果
func (auth) password(c *gin.Context) {
	// 定义一个用于保存请求参数的结构体变量
	var params inout.AuthPwReq
	// 将请求参数绑定到params结构体，若出错则返回错误信息
	err := c.Bind(&params)
	if err != nil {
		Resp.Err(c, 20001, err.Error())
		return
	}
	// 从上下文中获取当前用户ID
	uid, _ := c.Get("uid")
	// 使用DB查询是否存在匹配的用户ID和旧密码（此处省略了查询结果赋值给oldCun的步骤，根据上下文推测）
	var oldCun int64
	db.Dao.Model(model.User{}).Where("id=? and password=?", uid, fmt.Sprintf("%x", md5.Sum([]byte(params.OldPassword))))
	// 如果查询到匹配的用户和旧密码，则更新密码
	if oldCun > 0 {
		// 生成新的密码哈希
		password, _ := bcrypt.GenerateFromPassword([]byte(params.NewPassword), bcrypt.MinCost)
		// 更新数据库中用户的密码
		db.Dao.Model(model.User{}).
			Where("id=? ", uid).
			Update("password", password)
	}
	// 返回成功响应
	Resp.Succ(c, true)
}

func (auth) Logout(c *gin.Context) {
	Resp.Succ(c, true)
}
